package com.softaria.windows.config;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.softaria.windows.model.FloatPositionCalculator;
import com.softaria.windows.model.FloatSizeCalculator;
import com.softaria.windows.model.PerspectiveUrl;
import com.softaria.windows.model.ViewUrl;

/**
 * {@link MenuConfiguration} is the interface. DefaultMenuConfiguration is its
 * implementation. It is serializable class, which is ready to be moved via
 * GWT-remoting. So, it could be created on server side. Besides implementations
 * of {@link MenuConfiguration} methods it also has several methods for adding
 * data to it, such as addPerspective or addView.
 * 
 * @author Roman M Kuzmin (roman@softaria.com)
 * @see MenuConfiguration
 * 
 */
public class DefaultMenuConfiguration implements MenuConfiguration, Serializable {

  private static final String DEFAULT_HELP_TITLE = "";

  private static final long serialVersionUID = 1L;

  static class CommonProperties implements Serializable {
    private static final long serialVersionUID = 1L;
    private String label;
    private String defaultHelpMessage;
    private String defaultHelpTitle;

    protected CommonProperties() {

    }

    public CommonProperties(String label, String defaultHelpTitle, String defaultHelpMessage) {
      super();
      this.label = label;
      this.defaultHelpMessage = defaultHelpMessage;
      this.defaultHelpTitle = defaultHelpTitle;
    }

    public String getLabel() {
      return label;
    }

    public String getDefaultHelpMessage() {

      return defaultHelpMessage;
    }

    public String getDefaultHelpTitle() {

      return defaultHelpTitle;
    }

  }

  static class ViewProperties extends CommonProperties implements Serializable {
    private static final long serialVersionUID = 1L;

    protected ViewProperties() {

    }

    public ViewProperties(String label, String defaultHelpTitle, String defaultHelpMessage,
        FloatPositionCalculator positionCalculator, FloatSizeCalculator sizeCalculator) {
      super(label, defaultHelpTitle, defaultHelpMessage);
      this.positionCalculator = positionCalculator;
      this.sizeCalculator = sizeCalculator;
    }

    private FloatPositionCalculator positionCalculator;
    private FloatSizeCalculator sizeCalculator;

    public FloatPositionCalculator getPositionCalculator() {
      return positionCalculator;
    }

    public FloatSizeCalculator getSizeCalculator() {
      return sizeCalculator;
    }

  }

  private HashMap<PerspectiveUrl, List<ViewUrl>> viewsByPerspectives = new HashMap<PerspectiveUrl, List<ViewUrl>>();

  private PerspectiveUrl defaultPerspective;

  private List<PerspectiveUrl> perspecivesOrder = new ArrayList<PerspectiveUrl>();

  private HashMap<PerspectiveUrl, CommonProperties> properties = new HashMap<PerspectiveUrl, CommonProperties>();

  public PerspectiveUrl getDefaultPerspective() {
    return defaultPerspective;
  }

  public FloatPositionCalculator getDefaultPosition(ViewUrl viewUrl) {
    CommonProperties prp = properties.get(viewUrl);

    if (prp == null)
      return null;

    if (prp instanceof ViewProperties) {
      return ((ViewProperties) prp).getPositionCalculator();
    }

    return null;
  }

  public FloatSizeCalculator getDefaultSize(ViewUrl viewUrl) {
    CommonProperties prp = properties.get(viewUrl);

    if (prp == null)
      return null;

    if (prp instanceof ViewProperties) {
      return ((ViewProperties) prp).getSizeCalculator();
    }

    return null;
  }

  public String getMenuLabel(PerspectiveUrl url) {
    CommonProperties prp = properties.get(url);

    if (prp == null)
      return null;

    return prp.getLabel();
  }

  @Override
  public String getDefaultHelpMessage(PerspectiveUrl url) {
    CommonProperties prp = properties.get(url);

    if (prp == null)
      return null;

    return prp.getDefaultHelpMessage();
  }

  @Override
  public String getDefaultHelpTitle(PerspectiveUrl url) {
    CommonProperties prp = properties.get(url);

    if (prp == null)
      return null;

    return prp.getDefaultHelpTitle();
  }

  public List<PerspectiveUrl> getPerspecives() {

    return perspecivesOrder;
  }

  public List<ViewUrl> getViews(PerspectiveUrl perspective) {

    return viewsByPerspectives.get(perspective);
  }

  public void addPerspective(PerspectiveUrl url, String label, String defaultHelpTitle,
      String defaultHelpMessage) {
    perspecivesOrder.add(url);
    viewsByPerspectives.put(url, new ArrayList<ViewUrl>());
    properties.put(url, new CommonProperties(label, defaultHelpTitle, defaultHelpMessage));
  }

  @Deprecated
  /*
   * use addPerspective with title
   */
  public void addPerspective(PerspectiveUrl url, String label, String defaultHelpMessage) {

    addPerspective(url, label, DEFAULT_HELP_TITLE, defaultHelpMessage);
  }

  public void setDefaultPerspective(PerspectiveUrl defaultPerspective) {
    if (perspecivesOrder.contains(defaultPerspective)) {
      this.defaultPerspective = defaultPerspective;
    } else {
      throw new IllegalArgumentException("Bad perspective url " + defaultPerspective
          + " call addPerspective at first");
    }
  }

  @Deprecated
  /*
   * Use addView with help title!
   */
  public void addView(PerspectiveUrl perspective, ViewUrl url, String label,
      String defaultHelpMessage, FloatPositionCalculator posCalculator,
      FloatSizeCalculator sizeCalculator) {
    addView(perspective, url, label, DEFAULT_HELP_TITLE, defaultHelpMessage, posCalculator,
        sizeCalculator);
  }

  public void addView(PerspectiveUrl perspective, ViewUrl url, String label,
      String defaultHelpTitle, String defaultHelpMessage, FloatPositionCalculator posCalculator,
      FloatSizeCalculator sizeCalculator) {

    List<ViewUrl> views = viewsByPerspectives.get(perspective);

    if (views == null)
      throw new IllegalArgumentException("Bad perspective url " + perspective
          + " call addPerspective at first");

    views.add(url);

    properties.put(url, new ViewProperties(label, defaultHelpTitle, defaultHelpMessage,
        posCalculator, sizeCalculator));
  }

}
